/*
 *   Copyright (C) <2009> 
 *
 *   <Sandeep K Sinha> Complete rewrite.
 *   <Rishi B Agrawal> <Vineet Agarwal> <Rohit Vashist> <Rohit K Sharma> <Sneha Hendre> 
 *   
 *   <sandeepksinha@gmail.com> <rishi.b.agrawal@gmail.com> <checkout.vineet@gmail.com> 
 *   <rohit.k.vashist@gmail.com> <imreckless@gmail.com> <sneha.hendre@gmail.com>
 *
 *   This program is free software: you can redistribute it and/or modify it 
 *   under the terms of the GNU General Public License as published by the 
 *   Free Software Foundation, either version 3 of the License, or (at your 
 *   option) any later version->
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE->  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *    
 */

#define _GNU_SOURCE
#include <getopt.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "../include/ohsm.h"
#include "ohsm_u.h"

#define SET 1
#define UNSET 0
#define MAX_ARG_LENGTH 256 

int ohsm_fd;

/* 
 * print_ohsm_error() displays OHSM_ERRor messages
 * corresponding to OHSM_ERRor number in parameter ch
 */

void 
print_ohsm_error (int ch) {

	if (ch) printf("\nOHSM: OHSM_ERRor from the OHSM Kernel Driver.");

	switch(ch){

		case OHSM_ERR_DISP_DEVICE:
			printf("\nOHSM: OHSM_ERRor displaying device info");
			break;

		case OHSM_ERR_DISP_ALLOC:
			printf("\nOHSM: OHSM_ERRor displaying allocation policy");
			break;
		
		case OHSM_ERR_DISP_RELOC:
			printf("\nOHSM: OHSM_ERRor displaying relocation policy");
			break;

		case OHSM_ERR_MNTPNT:
			printf("\nOHSM: Incorrect Mountpoint.");
			break;

		case OHSM_ERR_ADMIN:
			printf("\nOHSM: Incorrect admin pointer.");
			break;

		case OHSM_ERR_ALLOC_PTR:
			printf("\nOHSM: OHSM_ERRor in allocation policy."); 
			break; 

		case OHSM_ERR_ALLOC:
			printf("\nOHSM: Incorrect allocation policy.");
			break;

		case OHSM_ERR_RELOC_PTR:
			printf("\nOHSM: OHSM_ERRor in relocation policy.");
			break; 

		case OHSM_ERR_RELOC:
			printf("\nOHSM: Incorrect relocation policy.");
			break;

		case OHSM_ERR_RELOCATE:
			printf("\nOHSM: OHSM_ERRor relocating files.");
			break;

		case OHSM_ERR_RULE_BITMAP:
			printf("\nOHSM: Rule bitmap incorrect.");
			break;

		case OHSM_ERR_ALREADY_DISABLED:
			printf("\nOHSM: OHSM already disabled.");
			break;

		case OHSM_ERR_OHSM_INACTIVE:
			printf("\nOHSM: OHSM is disabled now.");
			break;

		case OHSM_ERR_FS:
			printf("\nOHSM: OHSM_ERRor returned from the file system.");
			break;

		case OHSM_ERR_NULL_PTR:
			printf("\nOHSM: Null Pointer.");
			break;

		case OHSM_ERR_ENOMEM:
			printf("\nOHSM: Memory allocation failed.");
			break;	

		case OHSM_ERR_RELOC_ON:
			printf("\nOHSM: Relocation in progress.");
			break;

		case OHSM_ERR_RELOC_INACTIVE:
			printf("\nOHSM: OHSM is currently disabled.");
			break;

		case OHSM_ERR_ALREADY_EN:
			printf("\nOHSM: OHSM is already active.");
			break;
		
		case OHSM_ERR_INO_NOEXIST:
			printf("\nOHSM: File does not exist.");
			break;
	
		case OHSM_SUCCESS:
			printf("\nOHSM: Command executed successfully.");
			break;

		default:
			printf("\nOHSM: Unknown OHSM_ERRor code = %d.", ch);
			break;
	}
	printf("\n");
}

/*
 * print_tier_info () displays the tier device
 * information currently in use
 */
 
void 
get_tier_info (void) {
	
	int ret = 0;
	
	dev_info = (struct ohsm_tier_dev_info *) malloc (sizeof (struct ohsm_tier_dev_info));
	ret = ioctl (ohsm_fd, OHSM_GET_TIER_INFO, dev_info);
	if (ret) {
		print_ohsm_error (ret);
		return;
	}
	print_device_topology(); 
}

/*
 * print_alloc_policy() displays the current
 * allocation policy in use
 */
 
void 
get_alloc_policy (void) { 
	
	int ret = 0;
	
	allocpol = (struct ohsm_allocation_policy *) malloc (sizeof (struct ohsm_allocation_policy));
	ret = ioctl (ohsm_fd, OHSM_GET_ALLOC_POL, allocpol);
	if (ret) {
		print_ohsm_error (ret);
		return;
	}
	print_allocation_policy(); 
}
 
/*
 * print_reloc_policy() displays the current
 * relocation policy in use
 */
 
void 
get_reloc_policy (void) {
	
	int ret = 0;
	
	relocpol = (struct ohsm_reloc_policy *) malloc (sizeof (struct ohsm_reloc_policy));
	ret = ioctl (ohsm_fd, OHSM_GET_RELOC_POL, relocpol);
	if (ret) {
		print_ohsm_error (ret);
		return;
	}
	print_relocation_policy(); 
}

/* 
 * run_debug() displays debugging information
 * 1. Displays sam table
 * 2. Displays inode info
 * 3. Runs a demo for relocation on specified inode 
 */

int 
debug_relocate (void) {
	
	int ret = 0;
	struct ohsm_debug_reloc reloc_demo;
		
	printf("\nOHSM: Enter inode Number : ");
	scanf("%lu", &reloc_demo.inum);
	printf("\nOHSM: Enter destination Tier : ");
	scanf("%d", &reloc_demo.dest);
	ret = ioctl (ohsm_fd, DEMO_RELOC, &reloc_demo);	
	if (ret)
		printf("\nOHSM: Unable to run relocation demo.");	
	else
		print_ohsm_error (ret);
	return ret;
}

int 
debug_get_sam() {
	
	int ret = 0;
	
	ret = ioctl (ohsm_fd, DISPLAY_SAM, NULL); 
	if (!ret)
		printf("\nOHSM: SAM printed. Check dmesg.\n");
	else
		print_ohsm_error (ret);
	return ret;	
}

int 
debug_get_files (void) {
	
	int ret = 0;
	
	ret = ioctl(ohsm_fd, DISPLAY_INODES, NULL);
	if (!ret)
		printf("\nOHSM: Use dmesg to see results.\n");		
	else
		print_ohsm_error (ret);
	return ret;	
}

/*
 * _ohsm_select_relocate() is used for triggering 
 * relocation uses rule bitmap to identify 
 * rules
 */

int 
_ohsm_select_relocate (unsigned long rule_bitmap) {

	int ret = 0;
	char input;
	
	printf("\nOHSM: Are you sure (y/n) : ");
	input = getchar();
	
	if (input == 'y' || input == 'Y') 
		ret = ioctl (ohsm_fd, OHSM_SELECT_RELOCATION, &rule_bitmap); 
	else 
		printf("\nOHSM: Relocation Cancelled Successfully.");
	
	print_ohsm_error (ret);
	return ret;
}

int 
ohsm_select_relocate (int argc,char *argv[]) {
	
	int i, ret = 0;
	unsigned long rule_bitmap = 0, temp = 1,temp2;

	for (i = 0; i < argc - 2; i++){
		temp = 1;
		temp2 = strtoul (argv[i+2], NULL, 10);
		if (temp2 > MAX_RULES) {
			printf("\nOHSM: Invalid rule number %lu. Maximum number of rules supported are %d", temp2, MAX_RULES); 
			ret = OHSM_ERROR;
		}
		rule_bitmap =  rule_bitmap | temp << (temp2 - 1);
	}
	
	if (rule_bitmap == 0) {
		printf("\nOHSM: Invalid rule number specified");
		ret = OHSM_ERROR;
	}
	ret = _ohsm_select_relocate (rule_bitmap); 
	
	return ret;	
}

int 
ohsm_relocate (void) {
	
	int ret = 0;
	char input;
	unsigned long ar = 0 ;
	
	printf("\nOHSM: Are you sure (y/n) : ");
	input = getchar();
	
	if (input == 'y' || input == 'Y') 
		ret = ioctl (ohsm_fd, OHSM_RELOCATION, ar);
	else 
		printf("\nOHSM: Relocation Cancelled Successfully.");
	
	print_ohsm_error (ret);
	return ret;
}

/* disable_OHSM() disables OHSM 
 * sets OHSM_enabled flag to 0
 */

int 
ohsm_disable (void) {

	int ret=0;

	ret = ioctl(ohsm_fd, DISABLE_OHSM, NULL);	
	
	if (!ret)
		printf("\nOHSM: OHSM disabled successfully.");
		print_ohsm_error(ret);

	return ret;
}

/* OHSM_start() takes input the policy files and 
 * calls the parser to parse the file.
 * After successfully parsing the file it passes policies
 * to OHSM char driver to enable OHSM
 */

int 
ohsm_enable (char *alloc_file, char *reloc_file, char *tier_file,
							char *mountpoint, char *device_file) {
	
	int ret = 0;
	struct ohsm_tier_device_count *xml_dev_file = NULL;
	struct ohsm_struct_rules *xml_relocate_file = NULL;
	struct ohsm_allocation_policy *xml_alloc_file = NULL;
	struct ohsm_struct_for_ioctl input_to_kernel;

	/*
	 * Allocation of memory for various policies.
	 */

	dev_info = (struct ohsm_tier_dev_info *) malloc(sizeof(struct ohsm_tier_dev_info));
	allocpol = (struct ohsm_allocation_policy *) malloc(sizeof(struct ohsm_allocation_policy));
	relocpol = (struct ohsm_reloc_policy *) malloc(sizeof(struct ohsm_reloc_policy));

	/*
	 * Check if any of the allocation failed.
	 */

	if (!dev_info || !allocpol || !relocpol) {
		printf("\nOHSM: insufficeint memory");
		return OHSM_ERROR;
	}

	/*
	 * Initilize the various data structures.
	 */

 	dev_info->dinfo_count = 0;	
	
	allocpol->uidx = 0;
	allocpol->gidx = 0;
	allocpol->tidx = 0;

	relocpol->cnt_policies = 0;
	relocpol->pidx = 0;

	/*
	 * Get the device topology from libdevmaper.
	 */

	ret = ohsm_get_device_topology (device_file);

	if (ret) {
		printf("\nOHSM: Device topology cannot be fetched\n");	
		return ret;
	}

	/*
	 * Call the parser to fill in the tier device information.
	 */

	ret = ohsm_get_tier_device_info (tier_file);
	if (ret) {
		printf("\nOHSM: Parse OHSM_ERRor. Tier device file = %s\n", tier_file);
		return ret;
	}

	/*
	 * Call the parser to fill in the allocation policies.
	 */
	
	ret = ohsm_get_allocation_policy (alloc_file);
	if (ret) {
		free (xml_dev_file);
		printf("\nOHSM: Parse OHSM_ERRor. Allocation policy file %s\n", alloc_file);
		return OHSM_ERROR;
	}

	/*
	 * Call the parser to fill in the relocation policies.
	 */
	ret = ohsm_get_relocation_policy (reloc_file);	    
	if (ret) {
		free (xml_dev_file);
		free (xml_alloc_file);
		printf("\nOHSM: Parse OHSM_ERRor. Relocation policy file %s\n", reloc_file);
		return OHSM_ERROR;
	}

	/*
	 * Prepare the data structure for ioctl for enabling OHSM.
	 */
	input_to_kernel.ptr_reloc_policy = relocpol;
	input_to_kernel.ptr_alloc_policy = allocpol;
	input_to_kernel.ptr_dev_file = dev_info;
	strcpy(input_to_kernel.mountpoint, mountpoint);

	/*
	 * IOCTL to enable OHSM.
	 */
	ret = ioctl (ohsm_fd, IOC_OHSM_ENABLE, &input_to_kernel);	
	if (ret) {
		
		/*
		 * Free the allocated memeory.
		 */
		free (xml_dev_file);
		free (xml_alloc_file);
		free (xml_relocate_file);
		print_ohsm_error (ret);
		return ret;
	}
	
	printf("\nOHSM: OHSM Enabled Successfully \n");
	return OHSM_SUCCESS;
}

/* OHSM_status() displays the status of OHSM
 * displays enabled or disabled corresponding
 * to the OHSM state.
 */

void 
ohsm_status (void) {

  	int ret = 0;

	ret = ioctl (ohsm_fd, OHSM_STATUS, NULL);
	if (!ret) 
		printf("\nOHSM: OHSM is enabled\n");
	else
		printf("\nOHSM: OHSM is disabled\n");     
}


int
set_tier_info(char *device, char *tier_file) {
	
 	int ret = 0;
	
	/*
	 * Allocation of memory 
	 */

	dev_info = (struct ohsm_tier_dev_info *) malloc(sizeof(struct ohsm_tier_dev_info));
	memset (dev_info, 0, sizeof(struct ohsm_tier_dev_info));
	
	/*
	 * Check if the allocation failed.
	 */

	if(!dev_info) {
		printf("\nOHSM: insufficeint memory");
		return OHSM_ERROR;
	}
	
	/*
	 * Initilize the various data structures.
	 */
	dev_info->dinfo_count = 0;	

	/*
	 * Get the device topology from libdevmaper.
	 */

	ret = ohsm_get_device_topology (device);

	if (ret) {
		printf("\nOHSM: Device topology cannot be fetched\n");	
		return ret;
	}

	/*
	 * Call the parser to fill in the tier device information.
	 */

	ret = ohsm_get_tier_device_info (tier_file);
	if (ret) {
		printf("\nOHSM: Parse OHSM_ERRor. Tier device file = %s\n", tier_file);
		return ret;
	}

	ret = ioctl (ohsm_fd, OHSM_SET_TIER_INFO, dev_info);	
	if (ret) {
		printf("\nOHSM: Unable to assign tier device info");
		print_ohsm_error (ret);
		return ret;
	}
	printf("\nOHSM: New Tier Device Information Entered Successfully \n");
	return OHSM_SUCCESS;
}	

int 
set_reloc_policy (char *reloc_file) {
	
	int ret = 0;
	struct ohsm_struct_rules *xml_relocate_file = NULL;
	/*
	 * Allocation of memory 
	 */
	relocpol = (struct ohsm_reloc_policy *) malloc (sizeof (struct ohsm_reloc_policy));
	/*
	 * Check if the allocation failed.
	 */

	if (!relocpol) {
		printf("\nOHSM: insufficeint memory");
		return OHSM_ERROR;
	}
	/*
	 * Initilize the various data structures.
	 */
	relocpol->cnt_policies = 0;
	relocpol->pidx = 0;
	
	/*
	 * Call the parser to fill in the relocation policies.
	 */
	ret = ohsm_get_relocation_policy (reloc_file);	    
	if (ret) {
		printf("\nOHSM: Parse OHSM_ERRor. Relocation policy file %s\n", reloc_file);
		return OHSM_ERROR;
	}
	/*
	 * IOCTL to Set Relocation Policy.
	 */
	ret = ioctl (ohsm_fd, OHSM_SET_RELOC_POL, relocpol);	
	if (ret) {
		/*
		 * Free the allocated memeory.
		 */
		free (xml_relocate_file);
		print_ohsm_error (ret);
		return ret;
	}
	printf("\nOHSM: New Relocation Policy Entered Successfully \n");
	return OHSM_SUCCESS;
}

int 
set_alloc_policy (char *alloc_file) {

	int ret = 0;
	struct ohsm_allocation_policy *xml_alloc_file = NULL;
	/*
	 * Allocation of memory 
	 */
	allocpol = (struct ohsm_allocation_policy *) malloc (sizeof (struct ohsm_allocation_policy));
	
	/*
	 * Check if the allocation failed.
	 */

	if (!allocpol) {
		printf("\nOHSM: insufficeint memory");
		return OHSM_ERROR;
	}
	/*
	 * Initilize the various data structures.
	 */
	allocpol->uidx = 0;
	allocpol->gidx = 0;
	allocpol->tidx = 0;

	/*
	 * Call the parser to fill in the allocation policies.
	 */
	
	ret = ohsm_get_allocation_policy (alloc_file);
	if (ret) {
		printf("\nOHSM: Parse OHSM_ERRor. Allocation policy file %s\n", alloc_file);
		return OHSM_ERROR;
	}
	
	/*
	 * IOCTL to Set Allocation Policy.
	 */
	ret = ioctl (ohsm_fd, OHSM_SET_ALLOC_POL, allocpol);	
	if (ret) {
		/*
		 * Free the allocated memeory.
		 */
		free (xml_alloc_file);
		print_ohsm_error (ret);
		return ret;
	}
	printf("\nOHSM: New Allocation Policy Entered Successfully \n");
	return OHSM_SUCCESS;
}

void ohsm_help () {
	printf ("\n   Usage: ohsm optstring parameters\n");
	printf ("\n   -e    --enable \t\t enable ohsm");
	printf ("\n   -d    --disable \t\t disable ohsm");
	printf ("\n   -n    --get_state \t\t get status of ohsm");
	printf ("\n   -v    --debug_ioctl \t\t ioctl defined for debug");	
	printf ("\n   -r    --relocate \t\t relocate files");
	printf ("\n   -i    --device_info \t\t device info");
	printf ("\n   -a    --alloc_policy \t alloc_policy");
	printf ("\n   -p    --reloc_policy \t relocation policy ");
	printf ("\n   -s    --set_value \t\t set values");
	printf ("\n   -g    --get_value \t\t get values");
	printf ("\n   -w    --device_name \t\t device name ");
	printf ("\n   -x    --tierfile \t\t tier file");
	printf ("\n   -y    --allocfile \t\t allocation file");
	printf ("\n   -z    --relocfile \t\t relocation file");
	printf ("\n   -m    --mntpt \t\t mountpoint");
	printf ("\n   -t    --sam \t\t\t Block group mapping table");
	printf ("\n   -f    --files \t\t file on the mounted file system");
	printf ("\n   -o    --options_rules\t to provide the rule for relocation\n");
}

/* 
 *The main() function handles all the
 * commands OHSM provides
 */

int
main (int argc,char *argv[]) {

	int opt = 0, cmd_dbg = 0;
	int ret = 0, cmd = 0;
	unsigned int optionbits = 0;

	struct option longopts[] = {
		{"enable",			0,	NULL,	'e'}, 
		{"disable",			0,	NULL,	'd'}, 
		{"get_state",		1,	NULL,	'n'}, 
		{"debug_ioctl",		1,	NULL,	'v'}, 
		{"relocate",		1,	NULL,	'r'}, 
		{"device_info",		0,	NULL,	'i'}, 
		{"alloc_policy",		0,	NULL,	'a'}, 
		{"reloc_policy",		0,	NULL,	'p'}, 
		{"set_value",		1,	NULL,	's'}, 
		{"get_value",		1,	NULL,	'g'},
		{"device_name",		1,	NULL,	'w'}, 
		{"tierfile",		1,	NULL,	'x'}, 
		{"allocfile",		1,	NULL,	'y'}, 
		{"relocfile",		0,	NULL,	'z'}, 
		{"mntpt",			1,	NULL,	'm'}, 
		{"sam",			0,	NULL,	't'}, 
		{"files",			0,	NULL,	'f'},
		{"options_rules",		1,	NULL,	'o'}, 
		{0,0,0,0}
	};

	char reloc_file[MAX_ARG_LENGTH] = "";
	char alloc_file[MAX_ARG_LENGTH] = "";
	char mountpoint[MAX_ARG_LENGTH] = "";	
	char tier_file[MAX_ARG_LENGTH] = "";
	char device[MAX_ARG_LENGTH] = "";
	
	ohsm_fd = open ("/dev/ohsm", O_RDONLY);

	if (ohsm_fd <= 0) {
		printf("\nOHSM: Problem with /dev/ohsm");
		printf("\nOHSM: use cat /proc/devices");
		printf("\nOHSM: mknod /dev/ohsm c major 0\n"); 		
		return OHSM_ERROR;
	}	
	
	while ((opt = getopt_long (argc, argv, "w:x:y:z:m:o:s r v f g a p i t e d n h", longopts, NULL)) != -1) {

		switch(opt) {
			case 'h':
				optionbits |= OPT_FLAG_H;
				break;
				/*
				 * Used to enable OHSM.
				 * ohsm -e ....  
				 */ 
				 
			case 'e':
				optionbits |= OPT_FLAG_E;
				break;
			
				/*
				 * Used to disable OHSM.
				 * ohsm -s
				 */
			case 'd':
				optionbits |= OPT_FLAG_D;
				break;
			
				/*
				 * Used to get the current status of OHSM.
				 * ohsm -n
				 */	
			case 'n':
				optionbits |= OPT_FLAG_N;
				break;
				/*
				 * used for debug ioctls.
				 * ohsm -v 1 
				 * ohsm -v 2 
				 * ohsm -v 3 <ino> <dest_tier>
				 */
			case 'v':
				optionbits |= OPT_FLAG_V;
				break;	
				
				/*
				 * Used to trigger relocation.
				 * ohsm -r <rule_no>
				 */
			case 'r':
				optionbits |= OPT_FLAG_R;
				break;
				
			case 'o':
				optionbits |= OPT_FLAG_O;
				break;
			 
				 /*
				  * Used to pass the name of tier device file.
				  * ohsm <option> -i device.xml ....  
				  */ 
			case 'i':
				optionbits |= OPT_FLAG_I ;
				break; 

				 /*
				  * Used to pass the name of allocation policy file.
				  * ohsm <option> -a alloc.xml ....  
				  */ 

			case 'a':
				optionbits |= OPT_FLAG_A;
				break;

				 /*
				  * Used to pass the name of relocation policy file.
				  * ohsm <option> -o reloc.xml ....  
				  */ 
			case 'p':
				optionbits |= OPT_FLAG_P;
				break;
				
			case 'f':
				optionbits |= OPT_FLAG_F;
				break;

			case 's':
				optionbits |= OPT_FLAG_S;
				break;
			
			case 'g':
				optionbits |= OPT_FLAG_G;
				break;
			
			case 'w':
				strcpy (device, optarg);
				optionbits |= OPT_FLAG_W;
				break;
			
			case 'x':
				strcpy (tier_file, optarg);
				optionbits |= OPT_FLAG_X;
				break;
			
			case 'y':
				strcpy (alloc_file, optarg);
				optionbits |= OPT_FLAG_Y;
				break;
			
			case 'z':
				strcpy (reloc_file, optarg);
				optionbits |= OPT_FLAG_Z;
				break;
				
			case 'm':
				strcpy (mountpoint, optarg);
				optionbits |= OPT_FLAG_M;
				break;
			
			case 't':
				optionbits |= OPT_FLAG_T;
				break;
			/*
			 * Unused.
			 */

			case ':':
				printf ("Argument Missing");
				break;
			/*
			 * Invalid option.
			 */
			case '?':
				printf ("No such options declared");
				break;         
			
		}
	}	

	switch (optionbits) {
	
			case OHSM_HELP:
					ohsm_help();
					break;

			case OHSM_ENABLE: 
					ret = ohsm_enable (alloc_file, reloc_file, tier_file, mountpoint, device);
					break;
				
			case OHSM_DISABLE: 
					ohsm_disable();
					break;
				
			case OHSM_RELOCATE: 	
					ohsm_relocate();
					break;

			case OHSM_SELECT_RELOCATE: 
					ohsm_select_relocate (argc, argv);
					break;

			case OHSM_STATE:
					ohsm_status();
					break;

			case GET_ALLOC_POLICY: 
					get_alloc_policy();
					break;

			case GET_RELOC_POLICY: 
					get_reloc_policy();
					break;
	
			case GET_TIER_INFO: 
					get_tier_info ();
					break;
				
			case SET_ALLOC_POLICY: 
					set_alloc_policy (alloc_file);
					break;

			case SET_RELOC_POLICY:
					set_reloc_policy (reloc_file); 
					break;
	
			case SET_DEVICE_INFO: 
					set_tier_info (device, tier_file);
					break;
				
			case DEBUG_RELOCATE: 
					debug_relocate();	
					break;
			
			case DEBUG_GET_SAM: 
					debug_get_sam();
					break;
			
			case DEBUG_GET_FILES: 
					debug_get_files();	
					break;
				
			default:
					printf("\nOHSM: Invalid option %u", optionbits);
	}
	close(ohsm_fd);
	return ret;
}        
